#include "threadPool.h"
//第三期项目的头文件"03_header.h"
#include "03_header.h"
#define DB_HOST "localhost"   //127.0.0.1
#define DB_USER "root"        //登录mysql使用的用户名
#define DB_PASS "123456"      //登录mysql使用的密码
#define DB_NAME "netdisk_3"   //数据库名，已定好

void *threadFunc(void *arg){
    threadPool_t * pthreadPool = (threadPool_t *)arg;
    while(1){
        // 加锁
        int netfd;
        pthread_mutex_lock(&pthreadPool->mutex);
        while(pthreadPool->taskQueue.queueSize == 0 && pthreadPool->exitFlag == 0){
            pthread_cond_wait(&pthreadPool->cond, &pthreadPool->mutex);
        }
        if(pthreadPool->exitFlag == 1){
            printf("I am worker. I am going to exit!\n");
            pthread_mutex_unlock(&pthreadPool->mutex);
            pthread_exit(NULL);
        }
        netfd = pthreadPool->taskQueue.pFront->netfd;//获取队列队首
        printf("I am worker, I got netfd = %d\n", netfd);
        deQueue(&pthreadPool->taskQueue);
        pthread_mutex_unlock(&pthreadPool->mutex);

        printf("I am worker, do something!\n");
        //定义数据库指针并连接
        MYSQL *connect;

        connect = mysql_init(NULL);
        if(connect == NULL){
            fprintf(stderr, "mysql_init() failed.\n");
            exit(-1);
        }
        if (mysql_real_connect(connect, DB_HOST, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0) == NULL){
            fprintf(stderr, "mysql_real_connect() failed\n");
            mysql_close(connect);
            exit(-1);
        }

        //定义一个整数pwd，代表当前文件目录的id,随指令变化
        int pwd = -1;
        //定义一个base路径,为程序运行当前工作目录
        char basePath[1024];
        bzero(basePath, 1024);
        getcwd(basePath, 1024);

        //定义一个承载用户名的数组
        char username[1024];
        bzero(username, 1024);
        printf("启动目录：%s\n",basePath);
        while(1){
            int auth_ret = signInAndAuthPasswd(netfd, basePath, sizeof(basePath), username, connect);
            if(auth_ret == -2){
                //如果是删除目录
                continue;
            }
            if(auth_ret ==0){
                printf("登陆部分结束\n");
                break;
            }
        }


        //读取客户端发送的命令小火车
        train_t train;
        bzero(&train, sizeof(train_t));

        char tmpPath[1024];
        bzero(tmpPath, 1024);
        strcat(tmpPath, username);
        strcat(tmpPath, "/");
        strcat(tmpPath, train.value);

        //        //登陆成功后检测file_info是否有根目录，如果没有则增加，如果有则获得根目录id
        //        char query[1024];
        //        snprintf(query, sizeof(query),
        //                 "SELECT id, filename, username, parent_id, MD5, type, path FROM file_info WHERE username = '%s' AND parent_id = %d", username, -1);
        //        mysql_query(connect, query);
        //        MYSQL_RES *result;
        //        result = mysql_store_result(connect);
        //        if(mysql_num_rows(result) == 1){
        //            //本用户具有根目录，不再重复创建
        //        }
        //        if(mysql_num_rows(result) == 0){
        //            //本用户没有根目录，创建
        //            snprintf(query, sizeof(query),"INSERT INTO file_info (filename, username, parent_id, MD5, type, path) VALUES ('%s', '%s', -1, NULL, d, '%s')",
        //                     username, username, tmpPath);
        //            mysql_query(connect, query);
        //            printf("创建根目录成功\n");
        //            //获取根目录的id
        //            pwd = (int)mysql_insert_id(connect);
        //            printf("根目录id为%d.\n", pwd);
        //        }
        //        mysql_free_result(result);

        // 登陆成功后检测file_info是否有根目录
        char query[1024];
        snprintf(query, sizeof(query),
                 "SELECT id FROM file_info WHERE username = '%s' AND parent_id = -1 AND type = 'd'",
                 username);

        if (mysql_query(connect, query)) {
            fprintf(stderr, "查询失败: %s\n", mysql_error(connect));
            // 错误处理
        }

        MYSQL_RES *result = mysql_store_result(connect);
        if (result == NULL) {
            fprintf(stderr, "存储结果失败: %s\n", mysql_error(connect));
            // 错误处理
        }

        int root_id = -1;
        int row_count = mysql_num_rows(result);

        if (row_count == 1) {
            // 已有根目录，获取其ID
            MYSQL_ROW row = mysql_fetch_row(result);
            root_id = atoi(row[0]);
            printf("用户已有根目录，ID为%d\n", root_id);
        }
        else if (row_count == 0) {
            // 无根目录，创建
            //mysql_free_result(result);  // 先释放之前的查询结果

            // 创建根目录路径 - 示例使用"/username"格式
            char root_path[256];
            snprintf(root_path, sizeof(root_path), "%s/", username);

            snprintf(query, sizeof(query),
                     "INSERT INTO file_info (filename, username, parent_id, MD5, type, path) "
                     "VALUES ('%s', '%s', -1, '', 'd', '%s')",
                     username, username, root_path);

            if (mysql_query(connect, query)) {
                fprintf(stderr, "创建根目录失败: %s\n", mysql_error(connect));
            }

            root_id = (int)mysql_insert_id(connect);
            printf("创建根目录成功，ID为%d\n", root_id);
        }

        // 释放资源
        if (result) mysql_free_result(result);

        // 设置当前目录为根目录ID
        pwd = root_id;
        //承载LS指令返回的文件名字符串，文件名以空格分开
        char nameList[1024];
        while(1){

            bzero(nameList, 1024);
            int ret = recvRequest(netfd, &train);
            if(ret < 0){
                break;
            }
            switch(train.type){
            case CD:
                {
                    //如果输入cd 4，则在当前目录下增加4
                    //如果输入cd /4，则切换到根目录下增加4
                    //value是虚拟目录字符串，目录前增加"username/"
                    //jump_to_dir是找到虚拟目录对应的id
                    //change_dir是改变虚拟目录
                    //cd函数是change_dir

                    change_dir(tmpPath, train.value, username, &pwd, connect); 
                    if(pwd == 0){
                        printf("切换目录失败\n");
                    }
                    //tmpPath已经改变到cd后的位置
                    //pwd = jump_to_dir(tmpPath, connect);
                    //pwd已经改变为当前目录id
                    sendRequest(netfd, "SUCCESS", CD);
                    break;
                }
            case LS:
                {
                    //根据pwd找到所有parent id为pwd的项，并把这些文件/目录名装进数组返回
                    list_dir(pwd, nameList, connect); 
                    //把数组发给客户端
                    sendRequest(netfd, nameList, LS);
                    break;
                }
            case PUTS:
                {
                    //puts_file
                    //recvfile

                    printf("puts go in success.\n");
                    puts_file(netfd, connect, train.value, basePath, tmpPath, pwd, username);
                    break;
                }
            case GETS:
                {
                    //gets_file
                    //transfile
                    gets_file(connect, netfd, train.value, basePath);
                    break;
                }
            case REMOVE:
                {
                    remove_dir_or_file(connect, train.value, tmpPath, pwd, username);
                    break;
                }
            case PWD:
                {
                    //通过pwd整数获得当前目录，再根据path找到目录字符串并传给客户端
                    sendRequest(netfd, tmpPath, PWD);
                    break;
                }
            case MKDIR:
                {
                    printf("mkdir go in success.\n");
                    printf("tmpPath = %s.\n", tmpPath);
                    printf("train.value = %s.\n", train.value);
                    //接收目录名
                    add_dir(tmpPath, username, train.value, pwd, connect);
                    break;
                }
            case RMDIR:
                {
                    //接收要移除的目录名
                    remove_dir_or_file(connect, train.value, tmpPath, pwd, username);
                    break;
                }
            default:{
                        break;
                    }
            }
        }
        close(netfd);
    }
}
int makeWorker(threadPool_t *pthreadPool){
    for(int i = 0; i < pthreadPool->tidArr.workerNum; ++i){
        pthread_create(&pthreadPool->tidArr.arr[i],NULL,threadFunc,pthreadPool);
    }
    return 0;
}

